#ifndef ELIBC_LINKED_LIST_H
#define ELIBC_LINKED_LIST_H

#include "function.h"

typedef struct LinkedListIterator LinkedListIterator;
typedef struct LinkedList LinkedList;

// LinkedListIterator {

void * linkedListIteratorData(const LinkedListIterator * iterator);

LinkedListIterator * linkedListIteratorPrev(const LinkedListIterator * iterator);

LinkedListIterator * linkedListIteratorNext(const LinkedListIterator * iterator);

// }

// LinkedList {

LinkedList * linkedListNew(FunctionEqualTo equalTo, FunctionOnInserted onInserted, FunctionOnErased onErased);

void linkedListDelete(LinkedList * list);

LinkedListIterator * linkedListBegin(const LinkedList * list);

LinkedListIterator * linkedListEnd(const LinkedList * list);

int linkedListIsEmpty(const LinkedList * list);

void linkedListClear(LinkedList * list);

LinkedListIterator * linkedListInsert(LinkedList * list, LinkedListIterator * position, const void * data);

LinkedListIterator * linkedListErase(LinkedList * list, LinkedListIterator * position);

LinkedListIterator * linkedListFind(const LinkedList * list, const void * data);

LinkedListIterator * linkedListFindIn(const LinkedList * list, const LinkedListIterator * first, const LinkedListIterator * last, const void * data);

LinkedListIterator * linkedListFindIf(const LinkedList * list, const void * key, FunctionEqualTo equalTo);

LinkedListIterator * linkedListFindInIf(const LinkedList * list, const LinkedListIterator * first, const LinkedListIterator * last, const void * key, FunctionEqualTo equalTo);

void linkedListSplice(const LinkedList * list, LinkedListIterator * position, const LinkedList * another);

void linkedListSpliceAt(const LinkedList * list, LinkedListIterator * position, const LinkedList * another, LinkedListIterator * iterator);

void linkedListSpliceIn(const LinkedList * list, LinkedListIterator * position, const LinkedList * another, LinkedListIterator * first, LinkedListIterator * last);

void linkedListTransfer(const LinkedList * list, LinkedListIterator * position, const LinkedList * another, LinkedListIterator * first, LinkedListIterator * last);

void linkedListMarge(const LinkedList * list, const LinkedList * another);

// }

// LinkedListForInt {

LinkedList * linkedListForIntNew();

LinkedListIterator * linkedListForIntInsert(LinkedList * list, LinkedListIterator * position, int data);

LinkedListIterator * linkedListForIntFind(const LinkedList * list, int data);

LinkedListIterator * linkedListForIntFindIn(const LinkedList * list, const LinkedListIterator * first, const LinkedListIterator * last, int data);

// }

// LinkedListForUInt {

LinkedList * linkedListForUIntNew();

LinkedListIterator * linkedListForUIntInsert(LinkedList * list, LinkedListIterator * position, unsigned int data);

LinkedListIterator * linkedListForUIntFind(const LinkedList * list, unsigned int data);

LinkedListIterator * linkedListForUIntFindIn(const LinkedList * list, const LinkedListIterator * first, const LinkedListIterator * last, unsigned int data);

// }

#endif // ELIBC_LINKED_LIST_H
